Недавно я увидел пользовательский тип спящего. Я никогда не подвергался этому раньше. Я запишу его здесь как консолидацию своих знаний и позволю друзьям, которые никогда не подвергались участию, учиться и изучать его вместе.
1) Пользовательские типы, как следует из названия, являются, конечно, типами, которые реализуются сами по себе, поскольку внутренние типы не отвечают потребностям. Таких ситуаций не так много, но нам все еще нужно изучить это. Если у нас будет больше навыков, мы не будем подавлять наше тело. Также узнайте, как другие рассматривают, как думать о расширении при создании рамок.
Существует два способа реализации пользовательских типов, один из них состоит в том, чтобы внедрить пользовательский тип, другой - реализовать CompositeUsertype, и могут быть некоторые методы, но я пока не использовал его, поэтому я не буду говорить об этом сейчас.
Я использую только UserType на данный момент, давайте сначала посмотрим на определение интерфейса userType:
Общественный интерфейс usertype { /*** Возвращает коды типа SQL для столбцов, отображаемых по этому типу. Коды * определены на <tt> java.sql.types </tt>. */ public int [] sqltypes (); /*** Класс, возвращенный <tt> nullsafeget () </tt>. */ public class returnclass (); /*** Сравните два экземпляра класса, отображаемых этим типом для постоянства «равенство». * Равенство постоянного состояния. */ public boolean equals (объект X, объект Y) бросает hibernateexception; / ** * Получить хэшкод для экземпляра, в соответствии с постоянством «равенство» */ public int hashcode (объект x), бросает hibernateexception; /*** Получите экземпляр класса сопоставления из ResultSet JDBC. Реализации * должны обрабатывать возможность нулевых значений. */ public Object Nullsafeget (ResultSet RS, String [] имена, владелец объекта) бросает hibernateException, sqlexception; /*** Напишите экземпляр сфотографированного класса в подготовленное утверждение. Реализации * должны обрабатывать возможность нулевых значений. Многоколонный тип должен быть записан * для параметров, начиная с <tt> index </tt>. */ public void nullsafeset (подготовленная Statement, значение объекта, индекс int) бросает hibernateexception, sqlexception; /** * Верните глубокую копию постоянного состояния, останавливаясь в организациях и в * коллекциях. Нет необходимости копировать неподвижные объекты или нулевые * значения, и в этом случае безопасно просто вернуть аргумент. */ public объекта DeepCopy (значение объекта) бросает hibernateException; /*** Являются ли объекты такого типа измененными? * * @return boolean */ public boolean ismutable (); /*** Преобразовать объект в его кэшируемое представление. По крайней мере, этот * метод должен выполнить глубокую копию, если тип изменен. Однако этого может быть недостаточно * для некоторых реализаций; Например, ассоциации должны быть кэшированы как * значения идентификатора. (Необязательная операция) * * @param value объект, который будет кэширован * @return Кэшируемое представление объекта * @throhs hibernateexception */ public serializable disassmble (значение объекта) бросает hibernateexception; /*** Реконструируйте объект из кэшкового представления. По крайней мере, этот * метод должен выполнить глубокую копию, если тип изменен. (необязательная операция) */ Общественное собрание объекта (сериализуемая кэшированная, владелец объекта) бросает hibernateexception; /** * Во время слияния замените существующее (целевое) значение в сущности, которую мы объединяем с * с новым (исходным) значением из отдельного объекта, которую мы объединяем. Для обезжиренных * объектов или нулевых значений безопасно просто вернуть первый параметр. Для * изменяемых объектов безопасно вернуть копию первого параметра. Для объектов * со значениями компонентов может иметь смысл рекурсивно заменить значения компонентов. */ public Object Заменить (Object Original, цель объекта, владелец объекта) бросает hibernateexception; } На самом деле, вы можете понять это на английском в целом, поэтому я не буду объяснять это больше. Здесь главное, что мы должны реализовать метод nullsafeset (). Этот метод в основном использует сохранение этого типа значения в базе данных. На этот раз мы сначала узнаем, как его использовать, и тогда мы постепенно изучим, как он реализован внутри.
2) Примеры, которые я написал, когда изучал, были в примере Ся Синь, так что это определенно то же самое, что и большинство онлайн. Давайте просто проанализируем это примерно:
Ниже приведен пользовательский класс
пакет org.hibernate.tutorial.domain; импортировать java.io.serializable; импортировать java.util.list; Пользователь открытого класса реализует сериализуемый {public long Id; Приватное название строки; частный список электронных писем; Опустить метод get/set} Следующим является пользовательский класс Emaillist:
пакет org.hibernate.tutorial.domain; импортировать java.io.serializable; Импорт java.sql.preparedStatement; импортировать java.sql.resultset; Импорт java.sql.sqlexception; импортировать java.sql.sql.types; импортировать java.util.arraylist; импортировать java.util.list; Импорт org.hibernate.hibernate; Импорт org.hibernate.hibernateException; импорт org.hibernate.usertype.usertype; открытый класс Emaillist реализует usertype {private static final char splitter = ';'; Частный статический конечный int [] types = new int [] {types.varchar}; Private String Cassble (список emaillist) {StringBuilder strbuf = new StringBuilder (); for (int i = 0; i <emaillist.size () - 1; i ++) {strbuf.append (emaillist.get (i)). Append (splitter); } strbuf.append (emaillist.get (emaillist.size ()-1)); вернуть strbuf.toString (); } частный список parse (строка значения) {string [] strs = org.hibernate.util.stringHelper.split (value, string.valueof (splitter)); Список eMaillist = new ArrayList (); for (int i = 0; i <strs.length; i ++) {emaillist.add (strs [i]); } return emaillist; } public Object DeepCopy (значение объекта) бросает hibernateexception {список syrcelist = (list) value; Список ListList = new ArrayList (); TargetList.Add (Syscolist); вернуть список целей; } public serializable Disassemble (значение объекта) бросает hibernateexception {return null; } public boolean equals (объект x, объект y) бросает hibernateexception {if (x == y) вернуть true; System.out.println ("x:"+x+"y:"+y); if (x! = null && y! = null) {list xlist = (list) x; Список ylist = (list) y; if (xlist.size ()! = ylist.size ()) вернуть false; for (int i = 0; i <xlist.size (); i ++) {string str1 = (string) xlist.get (i); String str2 = (string) ylist.get (i); if (! str1.equals (str2)) вернуть false; } вернуть true; } вернуть false; } public boolean ismutable () {return false; } public Object Nullsafeget (ResultSet RS, String [] имена, владелец объекта) Throws HibernateException, SQLEXCEPTION {String Value = (String) hibernate.string.nullsafeget (rs, names [0]); if (value! = null) {return parse (value); // вставить список; Split} else {return null; }} public void nullsafeset (подготовленная Statement ST, значение объекта, int index) бросает hibernateexception, sqlexception {system.out.println ("set method выполнен!"); System.out.println ("value:" + value); if (value! = null) {string str = adsemble ((list) value); // Использовать строки; splice hibernate.string.nullsafeset (st, str, index); } else {hibernate.string.nullsafeset (st, value, index); }} открытый класс returnClass () {return list.class; } public int [] sqltypes () {return types; } // Опустите другие методы, которые не требуют модификации} Методы, реализованные в классе, представляют собой методы, которые необходимо изменить, и другие методы, которые не должны быть изменены в настоящее время, не были записаны, но их все равно необходимо реализовать.
3) Следующим является файл отображения пользовательского класса:
<class name="User" table="USER"> <id name="id" column="USER_ID" type="java.lang.Long"> <generator /> </id> <property name="name" type="string" column="USER_NAME"/> <property name="emails" type="org.hibernate.tutorial.domain.EmailList" column="emails"/> </class>
Я считаю, что все знают, как это изменить, и я не буду объяснять это здесь. В основном это меняет тип электронных писем и меняет их на класс Emaillist, который мы только что определили.
4) Наконец, давайте напишем тестовый класс:
импортировать java.util.hashmap; импортировать java.util.list; импортировать java.util.map; импортировать java.util.arraylist; Импорт junit.framework.testcase; Импорт org.hibernate.entityMode; Импорт org.hibernate.session; Импорт org.hibernate.sessionFactory; Импорт org.hibernate.transaction; Импорт org.hibernate.cfg.configuration; Импорт org.hibernate.tutorial.domain.user; открытый класс hibernatetest extends testcase {частная сессия = null; Protected void setup () бросает исключение {configuration cfg = new configuration (). configure (); SessionFactory SessionFactory = cfg.BuildSessionFactory (); session = sessionfactory.opensession (); } public void testinsert () {transaction tran = null; try {tran = session.beginTransaction (); Пользователь пользователь = новый пользователь (); user.setname ("Shun"); Список списка = new ArrayList (); list.add ("[email protected]"); list.add ("[email protected]"); user.setemails (список); session.save (пользователь); tran.commit (); } catch (Exception ex) {ex.printstackTrace (); if (tran! = null) {tran.rollback (); }} Protected void teardown () throws exception {session.close (); }} Здесь может быть проблема. Когда мы сохраняем только одно электронное письмо, у него будет исключение. Поле электронной почты в базе данных пусто. Когда у нас будет два кода, такие как приведенный выше код, проблем не будет. Результат в базе данных, как показано на рисунке:
И когда мы сохраняем только один, исключение заключается в следующем:
java.lang.classcastexception: java.util.arraylist не может быть поднят на java.lang.string
Это происходит в методе Equals Emaillist, String Str1 = (String) xlist.get (i); В этом коде, после проверки, он становится списком списка при внедрении данных и передаче их методу emaillist Nullsafeset, то есть
Значение: [[[email protected], [email protected]]]] Эта форма вызовет проблемы при сравнении. У него всегда есть только одно значение, но при сравнении это отличается.
if (xlist.size ()! = ylist.size ()) вернуть false;
Так что при кастинге будут проблемы.
После проверки метод равных:
X: [[[email protected], [email protected]]] y: [[email protected], [email protected]]
Этот результат очень странно. Интернет не говорил о том, почему эта ситуация произошла. Позвольте мне предложить это здесь: Версия Hibernate, которую я использую, Hibernate 3.3.2.ga. Я не знаю, является ли это проблемой версии или другой проблемой, давайте изучим ее завтра. Если кто -нибудь знает почему, я надеюсь, что скажу мне.