If this uncertainty table also needs our war to create, how to achieve. The native sql,entitymanager of the CREATE table cannot be performed because it is not a transaction that can be rolled back. In this case, we need to: capture an exception that does not exist in the table to implement table creation from the original connection.
getting connection to get connection from Entitymanage relies on the concrete implementation of JPA, which is supported by eclipse, but Hibernate is not supported.
Can be obtained through unwrap, unfortunately hibernate does not support
Connection conn = Entitymanager.unwrap (connection.class);
If we need to use the Hibernate proprietary API, we can take advantage of unwrap () to get hibernate session sessions
= Entitymanager.unwrap ( Session.class);
Blocked, we need to get from the datasource.
throw an exception when you need to create a table
public class Wantcreatetableexception extends runtimeexception{
private static final long serialversionuid = 1L;
Public wantcreatetableexception (String message) {
super (message);
}
}
Modify the code for the warehouse
@Repository @Validated public class Eventrepository {private static final Logger log = Logmanager.getlogger ();
private static final Gson Gson = new Gson ();
@PersistenceContext private Entitymanager Entitymanager;
@Inject private DataSource DataSource; private static final String Create_table_sqlformat = "CREATE TABLE IF not EXISTS '%s ' (" + "' ID ' bigint () unsigned not
NULL auto_increment, "+" ' Data ' text, "+" PRIMARY KEY (' id ') "+") Engine=innodb DEFAULT Charset=utf8 ";
public void CreateTable (string tablename) {String sql = String.Format (Create_table_sqlformat, TableName);
Try (Connection conn = Datasource.getconnection ();
PreparedStatement PS = conn.preparestatement (sql);) {ps.execute ();
}catch (SQLException e) {log.error ("(SQL error) Try to create TABLE {} error: {}", TableName, e.tostring ());
}} private String Gettablename () {...}
Public EventData FindOne (Long id) {log.traceentry ();
String tablename = Gettablename (); try{String sql = String.Format ("Select * from '%s ' WHERE ' id ' =?", Tablename,id); Return Eventdata.build (evententity) entitymanager.createnativequery (Sql,evententity.class). SetParameter (1, id).
Getsingleresult ());
}catch (Exception e) {return null; } public void Save (EventData event) {try{if (event.getid () = null | | Event.getid () = 0) This.insert (event
);
else This.update (event);
}catch (Exception e) {if (Istablenotexist (E, Gettablename ())) throw new Wantcreatetableexception (Gettablename ());
else throw e;
} Private Boolean update (EventData data) {...}
private void Insert (EventData data) {...} Private Boolean istablenotexist (Exception e,string tablename) {if (e.getcause () = null | | e.getcause (). Getcause () = nul
L) return false;
String message = E.getcause (). Getcause (). GetMessage ();
return stringutils.contains (Message, Tablename.concat ("' doesn ' t exist")); }
}
Use examples
@Service public
class Testservice {
@Transactional public
void Test2 () {
EventData event = new EventData ();
Event.adddata ("hello,world!");
This.eventRepository.save (event);
}
The following is just a test example, we call the warehouse in controller, this is not really good, controller should only call service, we can have a business logic service in the middle, its call Testservice to complete the relevant processing. @Transactional will exit the transaction in the face of RuntimeException, and the transaction is in the form of a proxy, that is, internal calls in this class do not work.
@Controller public
class TestController {
@Inject testpageservice testservice;
@Inject eventrepository eventrepository;
private void MyTest () {
try{
testservice.test2 ();
} catch (Wantcreatetableexception e) {
this.eventRepository.createTable (e.getmessage ());
Testservice.test2 ();}}
I tried to write as follows, but failed.
This has no effect, will still report transaction was marked for rollback only; Cannot commit;
My understanding is that wantcreatetableexception is just my encapsulated exception, and the source of the exception, has been triggered at the hibernate bottom of the rollback:
//serious: Servlet.service () for servlet [Springwebdispatcher] in context with path [/chapter22] threw exception
//[Request processing failed; nested Exception is org.springframework.orm.jpa.JpaSystemException:
//Transaction were marked for rollback only; cannot Commit Nested exception is org.hibernate.TransactionException:
//Transaction were marked for rollback only; cannot commit] wi th root cause
@Transactional (norollbackfor = wantcreatetableexception.class) public
void Test2 () {
EventData event = new EventData ();
Event.adddata ("hello,world!");
try{
This.eventRepository.save (event);
} catch (Wantcreatetableexception e) {
this.eventRepository.createTable (e.getmessage ());
This.eventRepository.save (event);
}
RELATED links: My professional Java for WEB applications related articles